home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
packdisk.arc
/
PACKDISK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-28
|
8KB
|
336 lines
//
// PackDisk v1.2, 9/28/90. Copyright 1990, Brad Davis.
// Unlimited distribution of unmodified source and executable permitted.
// bugs, suggestions, etc to bradd@gssc
//
// Suggested compilation for Microsoft C 6.0:
// cl /AC /W3 /WX packdisk.c setargv /link /NOE
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include <dos.h>
#include <types.h>
#include <stat.h>
#include <fcntl.h>
#include <io.h>
#include <conio.h>
typedef struct fINFO {
char *name;
long size;
struct fINFO *next;
} FINFO;
typedef struct diskfree_t DISKFREE;
typedef struct stat FILESTAT;
static char *shell;
//
// Insert a new file into our list, sorting by size as we go.
//
void insert (
FINFO **list,
FINFO *new
)
{
auto FINFO *cur;
auto FINFO **prev;
// Traverse the list until we find a file that is smaller.
for (prev = list, cur = *list;
cur;
prev = &cur->next, cur = cur->next)
{
// New one is bigger than this one ?
if (new->size > cur->size)
{
new->next = cur; // Yes, link small one below new
*prev = new; // and bigger one to new one
return;
}
}
// At the end of the list, so append the new (and smallest) one
*prev = new;
new->next = 0;
return;
}
//
// Copy the files over so that wasted space is minimized
//
int copy (
FINFO **list,
char *dest,
int cluster_size,
int avail_clusters
)
{
auto FINFO *cur;
auto FINFO **prev;
auto int remaining;
auto int err;
auto int clusters;
auto char destname[128];
// Set the clusters-remaining count
remaining = avail_clusters;
// Traverse the list
for (prev = list, cur = *list;
cur && remaining;
)
{
// Cache size of this file in clusters
clusters = (int) ((cur->size + (cluster_size - 1)) / cluster_size);
// Construct file name on destination device
strcpy (destname, dest);
strcat (destname, cur->name);
// Is this file too big to fit on the disk at all?
if ( clusters > avail_clusters)
{
printf ("Warning: %s too large (%ld) for destination media.\n",
cur->name, cur->size);
// Step to next in list
prev = &cur->next;
cur = cur->next;
continue;
}
// Copy file if it will fit
if (clusters <= remaining)
{
// Create the dest file to see if the directory can hold it
err = open (destname, O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
if (err == -1)
{
printf (" Root directory of disk is full (%ld bytes wasted)\n",
(long) cluster_size * remaining);
return (0); // Upper level should not see as an error
}
if (close (err) == -1)
{
printf ("Error creating directory entry for %s\n", cur->name);
return (1);
}
// Copy this one over
printf ("%8ld %s...", cur->size, cur->name);
err = spawnlp (P_WAIT, shell, shell, "/C", "COPY", cur->name, dest,
">", "NUL", (char *) 0);
if (err)
{
printf (" Error %d during copy\n", err);
return (1);
}
printf ("\n");
// Reduce clusters remaining count
remaining -= clusters;
// Now delete it from the list
*prev = cur->next; // previous points to next
// Do NOT step to the next entry
cur = *prev;
continue;
} else
{
// Step to next in list
prev = &cur->next;
cur = cur->next;
continue;
}
}
// Let the user know if any space remains on the disk
if (remaining)
{
printf ("%ld bytes remain on disk\n", (long) cluster_size * remaining);
}
return (0); // No error for now.
}
#ifdef DEBUG
//
// Print out the list in order
//
void printlist (
FINFO *list,
)
{
auto FINFO *cur;
for (cur = list;
cur;
cur = cur->next)
{
printf ("%8ld %s\n", cur->size, cur->name);
}
}
#endif
//
// Prompt for a new disk
//
int newdisk (
int drive,
int *cluster_size,
int *avail_clusters
) // returns 0 if all is well
{
auto DISKFREE df;
auto int err;
static char *dest = "X:";
static char *destdir = "X:\\";
auto int key;
do {
printf ("\n\nInsert disk for %c: and hit return (or Dir/Erase/Format/Label/Shell).\n",
drive + '@');
key = tolower (getch ());
*destdir = *dest = (char) (drive + '@');
if (key == 'd') {
err = spawnlp (P_WAIT, shell, shell, "/C", "DIR", dest, (char *) 0);
}
if (key == 'e') {
err = spawnlp (P_WAIT, shell, shell, "/C", "DEL", destdir,
(char *) 0);
}
if (key == 'f') {
err = spawnlp (P_WAIT, "QFORMAT", "QFORMAT", dest, (char *) 0);
}
if ( (key == 'l') || (key == 'f') ) {
err = spawnlp (P_WAIT, "LABEL", "LABEL", dest, (char *) 0);
}
if (key == 's') {
err = spawnlp (P_WAIT, shell, shell, (char *) 0);
}
}
while (key != '\r');
// Find out how much space is available on dest
err = _dos_getdiskfree (drive , &df);
if (err)
{
return (1);
}
// Set the number of clusters for each file
*cluster_size = df.sectors_per_cluster * df.bytes_per_sector;
*avail_clusters = df.avail_clusters;
printf (" Disk has %ld bytes free (%d x %d byte clusters)\n",
*avail_clusters * (long) *cluster_size,
*avail_clusters, *cluster_size);
return (0);
}
void main (
int argc,
char *argv[]
)
{
auto int err;
auto FINFO *list;
auto FINFO *files;
auto FINFO *fptr;
auto int drive;
auto int file;
auto int cluster_size;
auto int avail_clusters;
auto int number_files;
auto FILESTAT filestat;
// Validate the command line
if (argc < 3
|| strlen (argv[argc - 1]) != 2
|| argv[argc - 1][1] != ':'
|| (drive = toupper(argv[argc - 1][0]) - '@') < 0
)
{
printf ("PackDisk v1.2, 9/28/90. Copyright 1990, Brad Davis.\n\n");
printf ("Usage:\n");
printf (" packdisk file [file [...]] D:\n\n");
printf ("Copies source files to disks in the destination drive,\n");
printf ("using the minimum number of disks.\n\n");
exit (0);
}
shell = getenv ("COMSPEC");
if (!shell)
{
printf ("Cannot locate COMSPEC\n");
exit (1);
}
// Determine the number of source files and allocate storage for them
number_files = argc - 1 - 1; // 0 = our name, last = dest
files = (FINFO *) malloc (sizeof (FINFO) * number_files);
if (!files)
{
printf ("Error %d allocating for file list.\n", err);
exit (1);
}
// Build a list of all files
for (file = 0, fptr = &files[0]; file < number_files; file++, fptr++)
{
fptr->name = argv[file + 1];
// Get info on the file
err = stat (fptr->name, &filestat);
if (err)
{
printf ("Error %d reading %s.\n", err, fptr->name);
exit (1);
}
fptr->size = filestat.st_size;
fptr->next = (FINFO *) 0;
}
// Build a list of the files sorted by size (decreasing)
list = (FINFO *) 0;
for (file = 0, fptr = files; file < number_files; file++, fptr++)
{
// Add it to our list
insert (&list, fptr);
}
#ifdef DEBUG
printlist (list);
#endif
while (list)
{
err = newdisk(drive, &cluster_size, &avail_clusters);
if (err)
{
printf ("Error %d getting diskfree on drive %c:.\n",
err, drive + '@');
}
// Copy files, return 0 if ok
err = copy (&list, argv[argc - 1], cluster_size, avail_clusters);
if (err)
{
printf ("Error %d during copying.\n", err);
exit(1);
}
}
}